/**
* @Name: threejs
* @Desc: 机房
*/
<template>
  <div class="canvasGLTFBody">
    <div ref='canvasGLTF' class="canvasGLTF">
    </div>
  </div>
</template>

<script>
import * as THREE from 'three'
import jifang from './model/jifang.glb'
import {GLTFLoader} from 'three/addons/loaders/GLTFLoader';
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js';
import {CSS2DObject, CSS2DRenderer} from "three/addons/renderers/CSS2DRenderer.js";
import {machineRoomEquipment} from "@/api/api/LargeScreenData.js";

// 初始化用于记录动画帧ID的变量
var animationFrameId = null
// 初始化三维场景变量
var scene = null
// 初始化摄像机变量
var camera = null
// 初始化渲染器变量
var renderer = null
// 初始化ResizeObserver对象变量，用于监听DOM元素的大小变化
var resizeObserver = null
export default {
  name: 'machineRoom',
  data() {
    return {
      list: [],
      num: 0,
      showNumCard: false
    }
  },
// 当组件被挂载到DOM后执行的函数
  async mounted() {
    var that = this
    await this.getData()
    // 获取canvas的宽度和高度
    var width = that.$refs.canvasGLTF.offsetWidth
    var height = that.$refs.canvasGLTF.offsetHeight

    // 创建新的三维场景
    scene = new THREE.Scene();
    // 创建透视摄像机
    camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 1000);

    // 创建WebGL渲染器，并启用抗锯齿和透明度
    renderer = new THREE.WebGLRenderer({
      antialias: true,
      alpha: true
    });
    // 设置渲染器的大小
    renderer.setSize(width, height);

    // 创建并添加环境光
    var ambientLight = new THREE.AmbientLight(0xffffff);
    scene.add(ambientLight);

    // 创建并添加投影灯光
    var spotLight = new THREE.SpotLight(0xffffff);
    spotLight.position.set(13.173979758970319, 160, 100);
    spotLight.castShadow = true;
    scene.add(spotLight);

    // 设置摄像机的位置和视点

    camera.position.x = 13.173979758970319;
    camera.position.y = 5.467105824907211;
    camera.position.z = -3.0893406046917553;
    camera.lookAt(scene.position);

    // 创建GLTF加载器
    const loader = new GLTFLoader();
    // 加载glb模型
    loader.load(jifang, (gltf) => {
      const model = gltf.scene;
      scene.add(model);

      // 在加载完成后，遍历模型中的子对象以查找特定名称的对象
      function findObjectByName(name) {
        let result = null;
        model.traverse((child) => {
          if (child.isMesh && child.name === name) {
            result = child;
          }
        });
        return result;
      }

      // 使用名称查找对象并获取其坐标
      const cameraObject = findObjectByName('摄像机');
      const waterImmersionObject = findObjectByName('水浸');
      const tempHumidityObject = findObjectByName('温湿度');
      const lightObject = findObjectByName('灯光');
      const smokeSensorObject = findObjectByName('烟感');

      function generateLabelHTML(item) {
        let dataHTML = '';
        const statusClass = item.status === '在线' ? 'status-online' : 'status-offline';

        if (item.name === '温湿度') {
          dataHTML += `<div class="itemInfo">
                   <span>温度:</span><p>${item.data.find(d => d.name === '温度').value}</p>
                 </div>
                 <div class="itemInfo">
                   <span>湿度:</span><p>${item.data.find(d => d.name === '湿度').value}</p>
                 </div>`;
        } else if (item.name === '灯光') {
          dataHTML += `<div class="itemInfo">
                   <span>照明状态:</span><p>${item.data.find(d => d.name === '照明状态').value}</p>
                 </div>
                 <div class="itemInfo">
                   <span>调光值:</span><p>${item.data.find(d => d.name === '调光值').value}</p>
                 </div>`;
        }

        return `<div class="machineLabelInfo">
            <i class="icon iconfont ${item.icon}"></i>
          </div>
          <div class="infoPop" style="display: none;">
            <div class="infoPopName"><p>${item.name}</p></div>
            <i class="icon iconfont icon-close-circle"></i>
            <div class="infoPopBody">
              <div class="itemInfo">
                <span>状态:</span><p class="${statusClass}">${item.status}</p>
              </div>
              <div class="itemInfo">
                <span>时间:</span><p>${item.time}</p>
              </div>
              ${dataHTML}
            </div>
          </div>`;
      }

      function addLabelToModel(name, object, icon, item) {
        if (object) {
          // 创建一个包含 CSS2DObject 的容器 div
          const labelContainer = document.createElement('div');
          labelContainer.className = 'label';
          const label = new CSS2DObject(labelContainer);

          // 创建标签内容的 div
          const labelDiv = document.createElement('div');
          labelDiv.className = 'machineMain';

          labelDiv.innerHTML = generateLabelHTML(item)
          console.log(labelDiv.innerHTML)
          // 将标签内容 div 添加到容器 div
          labelContainer.appendChild(labelDiv);

          label.position.copy(object.position); // 设置标签的位置与模型一致

          // 添加点击事件处理程序，显示/隐藏 infoPop
          const machineLabelInfo = labelDiv.querySelector('.machineLabelInfo');
          const infoPop = labelDiv.querySelector('.infoPop');
          if (machineLabelInfo && infoPop) { // 添加检查，确保元素存在
            machineLabelInfo.addEventListener('click', () => {
              // 隐藏其他弹窗
              const allLabels = scene.children.filter(child => child instanceof CSS2DObject);
              allLabels.forEach(otherLabel => {
                if (otherLabel !== label) { // 与当前 label 不同
                  const otherInfoPop = otherLabel.element.querySelector('.infoPop');
                  if (otherInfoPop) { // 添加检查，确保元素存在
                    otherInfoPop.style.display = 'none';
                  }
                }
              });

              infoPop.style.display = 'block';
            });

            const closeIcon = labelDiv.querySelector('.icon-close-circle');
            closeIcon.addEventListener('click', () => {
              infoPop.style.display = 'none';
            });
          }

          scene.add(label);
        }
      }

// 示例：如何使用此函数与您的数据列表
      this.list.forEach(item => {
        console.log(item)
        const modelObjectMap = {
          '摄像机': cameraObject,
          '水浸': waterImmersionObject,
          '温湿度': tempHumidityObject,
          '灯光': lightObject,
          '烟感': smokeSensorObject
        };

        addLabelToModel(item.name, modelObjectMap[item.name], item.icon, item);
      });

      // 渲染函数
      function render() {
        // 请求下一帧的动画
        animationFrameId = requestAnimationFrame(render);
        // 渲染场景
        // console.log(camera.position)
        renderer.render(scene, camera);
        labelRenderer.render(scene, camera); // 渲染标签
      }

      // 调用渲染函数以开始渲染
      render();
    });

    // 将渲染器的DOM元素添加到Vue组件中的相应位置
    that.$refs.canvasGLTF.appendChild(renderer.domElement)
    // 创建CSS2DRenderer实例
    const labelRenderer = new CSS2DRenderer();
    labelRenderer.setSize(width, height);
    labelRenderer.domElement.style.position = 'absolute';
    labelRenderer.domElement.style.top = '0';
    labelRenderer.domElement.style.pointerEvents = 'none';
    that.$refs.canvasGLTF.appendChild(labelRenderer.domElement)
    var controls = new OrbitControls(camera, renderer.domElement);

    // 初始化尺寸观察者以监听canvas的大小变化
    that.initResizeObserver()
  },

  beforeDestroy() {
    // 在组件销毁之前，停止动画并释放资源
    cancelAnimationFrame(animationFrameId);
    renderer.dispose();
    scene.dispose();
    if (resizeObserver) {
      resizeObserver.disconnect();
    }
  },
  methods: {
    async getData() {
      try {
        const res = await machineRoomEquipment();
        this.list = res.data;
      } catch (err) {
        console.error(err);
      }
    },
    // 窗口自适应
    initResizeObserver() {
      resizeObserver = new ResizeObserver(entries => {
        for (let entry of entries) {
          if (entry.target === this.$refs.canvasGLTF) {
            const width = entry.contentRect.width;
            const height = entry.contentRect.height;
            camera.aspect = width / height;
            camera.updateProjectionMatrix();
            renderer.setSize(width, height);
            renderer.render(scene, camera);
          }
        }
      });
      resizeObserver.observe(this.$refs.canvasGLTF);
    },
  }
}
</script>

<style lang="scss" scoped>
.canvasGLTFBody {
  position: fixed;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: nowrap;
  flex-direction: column;
  align-content: flex-start;
}

.canvasGLTF {
  position: relative;
  margin: 0 auto;
  width: 100%;
  height: 100%;
}
</style>
<style lang="scss">
.machineMain {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: nowrap;
  flex-direction: row;
  align-content: flex-start;
  position: relative;

  .infoPop {
    position: absolute;
    left: 80px;
    top: 0;
    background: url("./assets/popbg.png") center center no-repeat;
    width: 252px;
    height: 174px;
    background-size: 100% 100%;

    .infoPopName {
      position: absolute;
      left: 0;
      top: 0;
      height: 40px;
      display: flex;
      justify-content: flex-start;
      align-items: center;
      flex-wrap: nowrap;
      flex-direction: row;
      align-content: flex-start;

      p {
        margin-left: 20px;
        font-size: 16px;
        font-family: AlibabaPuHuiTiR;
        font-weight: 400;
        background: -webkit-linear-gradient(#b9fffe, #ffffff); /* 您可以更改为您想要的颜色 */
        background: linear-gradient(#b9fffe, #ffffff); /* 您可以更改为您想要的颜色 */
        -webkit-background-clip: text;
        background-clip: text;
        color: transparent; /* 使原始文本颜色透明，只显示背景渐变色 */
      }
    }

    .infoPopBody {
      margin-top: 40px;
      width: calc(100% - 36px);
      margin-left: 18px;
    }

    .itemInfo {
      background: url("./assets/itembg1.png") center center no-repeat;
      width: 100%;
      height: 25px;
      background-size: 100% 100%;
      display: flex;
      justify-content: flex-start;
      align-items: center;
      flex-wrap: nowrap;
      flex-direction: row;
      align-content: flex-start;
      margin-top: 5px;

      span {
        margin-left: 10px;
        margin-right: 5px;
      }
    }

    .icon-close-circle {
      position: absolute;
      right: 10px;
      top: 20px;
      font-size: 18px;
      color: #fff;
    }
  }
}

.machineLabelInfo {
  width: 80px;
  height: 120px;
  background: url("./assets/labelAnimate.png") no-repeat;
  background-size: 100% 100%;
  pointer-events: initial;
  margin-bottom: 100%;
  display: flex;
  justify-content: flex-start;
  align-items: center;
  flex-wrap: nowrap;
  flex-direction: column;
  align-content: flex-start;

  i {
    margin-top: 35%;
    font-size: 30px;
    background: -webkit-linear-gradient(#89d9fe, #f8feff); /* 您可以更改为您想要的颜色 */
    background: linear-gradient(#89d9fe, #f8feff); /* 您可以更改为您想要的颜色 */
    -webkit-background-clip: text;
    background-clip: text;
    margin-left: 3px;
    color: transparent; /* 使原始文本颜色透明，只显示背景渐变色 */
  }
}

.label {
  /* 你的 label 样式 */
  cursor: pointer; /* 添加鼠标指针样式以指示可点击 */
  pointer-events: initial;

}

.infoPop {
  display: none; /* 默认隐藏 infoPop */
  pointer-events: initial;

}

.icon-close-circle {
  cursor: pointer; /* 添加鼠标指针样式以指示可点击 */
  pointer-events: initial;

}
.status-online {
  //color: green;
}

.status-offline {
  color: red;
}
</style>
